package com.lizi.idgenerator.config;

import com.lizi.idgenerator.dto.idcreator.IdCreatorResultModel;
import com.lizi.idgenerator.dto.ResultModel;
import com.lizi.idgenerator.service.IdCreatorService;
import com.lizi.idgenerator.service.impl.IdCreatorServiceImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * @author kingman
 * @since 2020-12-15 18:05
 */
@Component
public class IdConfig {

    private static Logger log = LoggerFactory.getLogger(IdConfig.class);

    /**
     * 队列
     */
    private ConcurrentHashMap<String, ConcurrentLinkedQueue<Long>> queue = new ConcurrentHashMap<String, ConcurrentLinkedQueue<Long>>();

    /**
     * 当队列长度小于此值时，再次刷新拿数据
     */
    private static final int minSize = 100;


    @Autowired
    private IdCreatorService idCreatorService;

    /**
     * 重新加载Id队列
     * @param idKey
     */
    public synchronized ConcurrentLinkedQueue<Long> refresh(String idKey){
        StopWatch stopWatch = new StopWatch();
        stopWatch.start("idCreatorService.generateId");
        StringBuilder sb = new StringBuilder();

        ConcurrentLinkedQueue<Long> concurrentLinkedQueue = queue.get(idKey);
        if(concurrentLinkedQueue==null){
            sb.append(String.format("Key:%s的队列为空，先创建字典值",idKey));
            concurrentLinkedQueue = new ConcurrentLinkedQueue<Long>();
            queue.put(idKey,concurrentLinkedQueue);
        }

        ResultModel<IdCreatorResultModel> idCreatorResultModelResultModel = idCreatorService.generateId(idKey);
        stopWatch.stop();
        sb.append(String.format(" idCreatorService.generateId,花费时间：%s",stopWatch.getTotalTimeMillis()));
        stopWatch.start("入列");
        if(!idCreatorResultModelResultModel.isSuccess()){
            log.error(idCreatorResultModelResultModel.getMessage());
            return null;
        }
        IdCreatorResultModel returnValue = idCreatorResultModelResultModel.getReturnValue();
        Long currentValue = returnValue.getCurrentValue();
        while (currentValue<returnValue.getCreatedValue()){
            currentValue++;
            concurrentLinkedQueue.add(currentValue);
        }
        stopWatch.stop();
        sb.append(String.format(" 入列,花费时间：%s",stopWatch.getTotalTimeMillis()));
        log.info(sb.toString());
        return concurrentLinkedQueue;
    }

    /**
     * 获取Id
     * @param idKey
     * @return
     */
    public synchronized Long getId(String idKey){
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        ConcurrentLinkedQueue<Long> concurrentLinkedQueue = null;
        concurrentLinkedQueue = queue.get(idKey);

        if (concurrentLinkedQueue == null) {
            concurrentLinkedQueue = refresh(idKey);
        }
        if (concurrentLinkedQueue == null) {
            log.error("获取Id出错。");
            throw new RuntimeException("获取Id出错");
        }


        StringBuilder sb = new StringBuilder();
        Long value = concurrentLinkedQueue.poll();
        if(concurrentLinkedQueue.size()<minSize)
        {
            refresh(idKey);
        }
        stopWatch.stop();
        sb.append(String.format("获取到值：%s，队列剩余量为：%s,花时：%s",value,concurrentLinkedQueue.size(),stopWatch.getTotalTimeMillis()));
        log.info(sb.toString());
        return value;
    }

}
